package com.cf.config;

import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;

/**
 * Druid配置
 *
 */
@MapperScan({ "com.cf.mapper", "com.cf.dao" })
@Configuration
public class DruidConfig {

	private Logger logger = LoggerFactory.getLogger(DruidConfig.class);

	@Value("${primary.spring.datasource.url:#{null}}")
	private String dbUrl;
	@Value("${primary.spring.datasource.username: #{null}}")
	private String username;
	@Value("${primary.spring.datasource.password:#{null}}")
	private String password;
	@Value("${primary.spring.datasource.driverClassName:#{null}}")
	private String driverClassName;
	@Value("${primary.spring.datasource.initialSize:#{null}}")
	private Integer initialSize;
	@Value("${primary.spring.datasource.minIdle:#{null}}")
	private Integer minIdle;
	@Value("${primary.spring.datasource.maxActive:#{null}}")
	private Integer maxActive;
	@Value("${primary.spring.datasource.maxWait:#{null}}")
	private Integer maxWait;
	@Value("${primary.spring.datasource.timeBetweenEvictionRunsMillis:#{null}}")
	private Integer timeBetweenEvictionRunsMillis;
	@Value("${primary.spring.datasource.minEvictableIdleTimeMillis:#{null}}")
	private Integer minEvictableIdleTimeMillis;
	@Value("${primary.spring.datasource.validationQuery:#{null}}")
	private String validationQuery;
	@Value("${primary.spring.datasource.testWhileIdle:#{null}}")
	private Boolean testWhileIdle;
	@Value("${primary.spring.datasource.testOnBorrow:#{null}}")
	private Boolean testOnBorrow;
	@Value("${primary.spring.datasource.testOnReturn:#{null}}")
	private Boolean testOnReturn;
	@Value("${primary.spring.datasource.poolPreparedStatements:#{null}}")
	private Boolean poolPreparedStatements;
	@Value("${primary.spring.datasource.maxPoolPreparedStatementPerConnectionSize:#{null}}")
	private Integer maxPoolPreparedStatementPerConnectionSize;
	@Value("${primary.spring.datasource.filters:#{null}}")
	private String filters;
	@Value("{primary.spring.datasource.connectionProperties:#{null}}")
	private String connectionProperties;

	@Bean // 声明其为Bean实例
	@Primary // 在同样的DataSource中，首先使用被标注的DataSource

	public DataSource dataSource() {
		DruidDataSource datasource = new DruidDataSource();

		datasource.setUrl(this.dbUrl);
		datasource.setUsername(username);
		datasource.setPassword(password);
		datasource.setDriverClassName(driverClassName);
//		logger.info("datasource dbtype=" + datasource.getDbType());
//		logger.info("datasource url=" + datasource.getUrl());
//		logger.info("datasource username=" + datasource.getUsername());
		// configuration
		if (initialSize != null) {
			datasource.setInitialSize(initialSize);
		}
		if (minIdle != null) {
			datasource.setMinIdle(minIdle);
		}
		if (maxActive != null) {
			datasource.setMaxActive(maxActive);
		}
		if (maxWait != null) {
			datasource.setMaxWait(maxWait);
		}
		if (timeBetweenEvictionRunsMillis != null) {
			datasource.setTimeBetweenEvictionRunsMillis(
					timeBetweenEvictionRunsMillis);
		}
		if (minEvictableIdleTimeMillis != null) {
			datasource
					.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		}
		if (validationQuery != null) {
			datasource.setValidationQuery(validationQuery);
		}
		if (testWhileIdle != null) {
			datasource.setTestWhileIdle(testWhileIdle);
		}
		if (testOnBorrow != null) {
			datasource.setTestOnBorrow(testOnBorrow);
		}
		if (testOnReturn != null) {
			datasource.setTestOnReturn(testOnReturn);
		}
		if (poolPreparedStatements != null) {
			datasource.setPoolPreparedStatements(poolPreparedStatements);
		}
		if (maxPoolPreparedStatementPerConnectionSize != null) {
			datasource.setMaxPoolPreparedStatementPerConnectionSize(
					maxPoolPreparedStatementPerConnectionSize);
		}

		if (connectionProperties != null) {
			datasource.setConnectionProperties(connectionProperties);
		}

		List<Filter> filters = new ArrayList<>();
		filters.add(statFilter());
		filters.add(wallFilter());
		datasource.setProxyFilters(filters);

		return datasource;
	}

	@Bean
	@Primary
	public ServletRegistrationBean druidServlet() {
		ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
		servletRegistrationBean.setServlet(new StatViewServlet());
		servletRegistrationBean.addUrlMappings("/druid/*");
		return servletRegistrationBean;
	}

	@Bean
	@Primary
	public StatFilter statFilter() {
		StatFilter statFilter = new StatFilter();
		statFilter.setLogSlowSql(true);
		statFilter.setMergeSql(true);
		statFilter.setSlowSqlMillis(1000);

		return statFilter;
	}

	@Bean
	@Primary
	public WallFilter wallFilter() {
		WallFilter wallFilter = new WallFilter();

		// 允许执行多条SQL
		WallConfig config = new WallConfig();
		config.setMultiStatementAllow(true);
		wallFilter.setConfig(config);

		return wallFilter;
	}

	@Bean
	@Primary
	public DataSourceTransactionManager transactionManager() {
		return new DataSourceTransactionManager(dataSource());
	}
}
